/*
 * Copyright (c) 2019.  drakelee.base All rights reserved.
 */

package com.base.components.database.service;

import com.base.components.common.constants.sys.Pages;
import com.base.components.common.dto.page.DataPage;
import com.base.components.common.util.ColumnsUtil;
import com.base.components.database.dao.base.JpaHelper;
import org.hibernate.transform.ResultTransformer;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * JpaService
 *
 * @param <T> 实体类
 * @param <ID> 实体类ID
 *
 * @author <a href="drakelee1221@gmail.com">LiGeng</a>
 * @version 1.0.0, 2018-02-13 10:21
 */
interface JpaService<T extends Serializable, ID extends Serializable> {

  /**
   * 查询该表所有实体对象列表
   *
   * @return List
   */
  List<T> findAll();

  /**
   * 排序查询该表所有实体对象列表
   *
   * @return List
   */
  List<T> findAll(Sort paramSort);

  /**
   * 根据ID集合查询该表所有实体对象列表
   *
   * @param paramIterable ID集合
   *
   * @return List
   */
  List<T> findAllById(Iterable<ID> paramIterable);

  /**
   * 根据分页对象，查询分页
   *
   * @param paramPageable 分页对象
   *
   * @return Page
   */
  Page<T> findAll(Pageable paramPageable);

  /**
   * 根据条件查询实体对象列表
   *
   * @param paramSpecification 查询条件
   *
   * @return List
   */
  List<T> findAll(Specification<T> paramSpecification);

  /**
   * 根据条件和分页对象，查询分页
   *
   * @param paramSpecification 查询条件
   * @param paramPageable 分页对象
   *
   * @return Page
   */
  Page<T> findAll(Specification<T> paramSpecification, Pageable paramPageable);

  /**
   * 根据条件和排序对象，查询列表
   *
   * @param paramSpecification 查询条件
   * @param paramSort 排序对象
   *
   * @return List
   */
  List<T> findAll(Specification<T> paramSpecification, Sort paramSort);

  /**
   * 查询总数
   *
   * @return long
   */
  long count();

  /**
   * 根据条件查询总数
   *
   * @param paramSpecification 查询条件
   *
   * @return long
   */
  long count(Specification<T> paramSpecification);

  /**
   * 根据ID返回一个实体对象的引用，如果为空，则抛出异常
   *
   * @param paramID ID
   *
   * @return T
   */
  T getOne(ID paramID);

  /**
   * 根据ID返回一个实体对象的引用，可能为空
   *
   * @param paramID ID
   *
   * @return T
   */
  T findById(ID paramID);

  /**
   * 根据条件查询一个实体对象，如果多余一个，则抛出异常
   *
   * @param paramSpecification 查询条件
   *
   * @return
   */
  T findOne(Specification<T> paramSpecification);

  /**
   * 根据ID判断是否存在于数据集
   *
   * @param paramID ID
   *
   * @return boolean
   */
  boolean existsById(ID paramID);

  /**
   * 更新（ID非空）或新增（ID为空）实体集合
   * @param entities 实体集合
   * @return entities
   */
  <S extends T> Iterable<S> saveAll(Iterable<S> entities);

  /**
   * 更新（ID非空）或新增（ID为空）实体
   * @param entity 实体
   * @return entity
   */
  <S extends T> S save(S entity);

  /**
   * 更新（ID非空）或新增（ID为空）实体，并刷新对数据库持久化对象的所有更改
   * @param entity 实体
   * @return entity
   */
  <S extends T> S saveAndFlush(S entity);

  /**
   * 根据ID删除
   * @param id -
   * @return 是否成功
   */
  boolean deleteById(ID id);

  /**
   * 根据ID集合删除
   * @param ids - ID集合
   * @return 删除行数
   */
  int deleteInBatch(Iterable<ID> ids);


  /**
   * 设置Query查询返回值为Map类型
   * @param listQuery - Nonnull  - 列表查询Query
   * @return Query
   */
  default Query setMapResult(Query listQuery){
    return JpaHelper.setMapResult(listQuery);
  }

  /**
   * 设置Query查询返回值类型
   * @param listQuery - Nonnull  - 列表查询Query
   * @param resultTransformer - Nonnull  - 返回值类型
   * @return Query
   */
  default Query setTransformerResult(Query listQuery, ResultTransformer resultTransformer){
    return JpaHelper.setTransformerResult(listQuery, resultTransformer);
  }

  /**
   * Query查询分页
   * @param countQuery  - Nonnull  - 总记录数查询Query
   * @param listQuery   - Nonnull  - 列表查询Query
   * @param pageNum     - Nullable - 当前页数，默认{@link Pages#PAGE_NUM}
   * @param pageSize    - Nullable - 每页行数，默认{@link Pages#PAGE_SIZE}
   *
   * @return DataPage
   */
  default <E> DataPage<E> pageByQuery(Query countQuery, Query listQuery, Integer pageNum, Integer pageSize){
    return JpaHelper.pageByQuery(countQuery, listQuery, pageNum, pageSize);
  }

  /**
   * Query查询分页
   * @param countQuery  - Nonnull  - 总记录数查询Query
   * @param listQuery   - Nonnull  - 列表查询Query
   * @param pageParams  - Nullable - 带当前页数，默认{@link Pages#PAGE_NUM}，和每页行数，默认{@link Pages#PAGE_SIZE}
   * @return DataPage
   */
  default <E> DataPage<E> pageByQuery(Query countQuery, Query listQuery, Map<String, ?> pageParams){
    return JpaHelper.pageByQuery(countQuery, listQuery, pageParams);
  }

  /**
   * Query查询分页, 每页行数无限制
   * @param countQuery  - Nonnull  - 总记录数查询Query
   * @param listQuery   - Nonnull  - 列表查询Query
   * @param pageNum     - Nullable - 当前页数，默认{@link Pages#PAGE_NUM}
   * @param pageSize    - Nullable - 每页行数，默认{@link Pages#PAGE_SIZE}
   * @return DataPage
   */
  default <E> DataPage<E> pageByQueryNoHelper(Query countQuery, Query listQuery, Integer pageNum, Integer pageSize){
    return JpaHelper.pageByQueryNoHelper(countQuery, listQuery, pageNum, pageSize);
  }
  /**
   * Query查询分页, 每页行数无限制
   * @param countQuery  - Nonnull  - 总记录数查询Query
   * @param listQuery   - Nonnull  - 列表查询Query
   * @param pageParams  - Nullable - 带当前页数，默认{@link Pages#PAGE_NUM}，和每页行数，默认{@link Pages#PAGE_SIZE}
   * @return DataPage
   */
  default <E> DataPage<E> pageByQueryNoHelper(Query countQuery, Query listQuery, Map<String, ?> pageParams){
    return JpaHelper.pageByQueryNoHelper(countQuery, listQuery, pageParams);
  }

  /**
   * 将实体类字段的 javax.persistence.Column 注解，生成数据库查询字段
   * @param domainClass -实体类名
   * @param alias - 表别名，如： t
   * @return String 格式： ${Column注解name} ${实体类字段}, ${Column注解name} ${实体类字段}, ....
   */
  default String findColumns(Class domainClass, String alias) {
    return ColumnsUtil.findColumns(domainClass, alias);
  }

  /**
   * 将实体类字段的 javax.persistence.Column 注解，生成对应 Map
   * @param domainClass -实体类名
   * @return Map [${实体类字段}=${Column注解name}]
   */
  default Map<String, String> findColumns(Class domainClass) {
    return ColumnsUtil.findColumns(domainClass);
  }
}
